package transform.app.editors;


import java.io.IOException;

import model.Graph;
import model.GraphDirector;
import model.GraphFactory;
import model.IGraphReader;
import model.Relationship;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;

import transform.app.editors.table.edit.HighCostEditingSupport;
import transform.app.editors.table.edit.LowCostEditingSupport;
import transform.app.editors.table.edit.MediumCostEditingSupport;
import transform.app.editors.table.edit.ProbRelationshipEditingSupport;
import transform.config.Cost;
import transform.config.TransformConfiguration;


/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
/**
 * An example showing how to create a multi-page editor.
 * This example has 3 pages:
 * <ul>
 * <li>page 0 contains a nested text editor.
 * <li>page 1 allows you to change the font used in page 2
 * <li>page 2 shows the words in page 0 in sorted order
 * </ul>
 */
public class AppEditor extends MultiPageEditorPart implements IResourceChangeListener{

	/** The text editor used in page 0. */
	private TextEditor editor;

	/** The font chosen in page 1. */
	private Font font;

	/** The text widget used in page 2. */
	private StyledText text;
	private TableViewerColumn relCost;
	private TableViewerColumn relTarget;
	private TableViewerColumn relSource;
	private TableViewer relationshipTable;
	private TableViewerColumn lowColumn;
	private TableViewerColumn mediumCol;
	private TableViewerColumn highColumn;
	private TableViewerColumn dependencesCol;
	private TransformConfiguration configuration;
	private TableViewer tableViewer1;
	private Button loadButton;
	private Composite composite3;
	private Composite composite2;
	private CLabel cLabel1;
	private Group group2;
	private Group group1;
	private Text fileName;

	private Graph graph;
	/**
	 * Creates a multi-page editor example.
	 */
	public AppEditor() {
		super();
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
	}
	
	/**
	 * Creates page 0 of the multi-page editor,
	 * which allows you to change the font used in page 2.
	 */
	void createPage1() {

		Composite composite = new Composite(getContainer(), SWT.NONE);
		FormLayout layout = new FormLayout();
		composite.setLayout(layout);
		composite.setSize(369, 219);
		{
			group1 = new Group(composite, SWT.NONE);
			FormLayout group1Layout = new FormLayout();
			group1.setLayout(group1Layout);
			FormData group1LData = new FormData();
			group1LData.width = 365;
			group1LData.height = 31;
			group1LData.left =  new FormAttachment(1, 1000, 0);
			group1LData.right =  new FormAttachment(1006, 1000, 0);
			group1LData.top =  new FormAttachment(2, 1000, 0);
			group1.setLayoutData(group1LData);
			group1.setText("Architecture");
			{
				cLabel1 = new CLabel(group1, SWT.NONE);
				FillLayout cLabel1Layout = new FillLayout(org.eclipse.swt.SWT.HORIZONTAL);
				cLabel1Layout.marginWidth = 30;
				cLabel1Layout.spacing = 6;
				cLabel1.setLayout(cLabel1Layout);
				FormData cLabel1LData = new FormData();
				cLabel1LData.width = 365;
				cLabel1LData.height = 31;
				cLabel1LData.left =  new FormAttachment(1, 1000, 0);
				cLabel1LData.right =  new FormAttachment(1001, 1000, 0);
				cLabel1LData.top =  new FormAttachment(16, 1000, 0);
				cLabel1LData.bottom =  new FormAttachment(1016, 1000, 0);
				cLabel1.setLayoutData(cLabel1LData);
				cLabel1.setText("File:");
				{
					composite2 = new Composite(cLabel1, SWT.NONE);
					FillLayout composite2Layout = new FillLayout(org.eclipse.swt.SWT.HORIZONTAL);
					composite2Layout.marginHeight = 6;
					composite2.setLayout(composite2Layout);
					{
						fileName = new Text(composite2, SWT.NONE);
						if(configuration.isFileSetted())
							fileName.setText(configuration.getFileName());
							
					}
					{
						composite3 = new Composite(composite2, SWT.NONE);
						FillLayout composite3Layout = new FillLayout(org.eclipse.swt.SWT.HORIZONTAL);
						composite3Layout.spacing = 5;
						composite3.setLayout(composite3Layout);
						{
							Button fontButton = new Button(composite3, SWT.NONE);
							fontButton.setText("Browse...");
							fontButton.addSelectionListener(new SelectionAdapter() {
								public void widgetSelected(SelectionEvent event) {
									FileDialog dialog = new FileDialog(getContainer().getShell(), SWT.NULL);
									String path = dialog.open();
									if (path != "" )
										fileName.setText(path);
								}
							});
						}
						{
							loadButton = new Button(composite3, SWT.NONE);
							loadButton.setText("Load");
							loadButton.addSelectionListener(new SelectionAdapter() {
								public void widgetSelected(SelectionEvent event) {
									configuration.setFileName(fileName.getText());
									try {
								{
								}
										loadGraph();
									} catch (IOException e) {
										MessageBox error = new MessageBox(getContainer().getShell(), SWT.ERROR);
										error.setMessage("El archivo no se pudo abrir...");
										error.open();
									}
								}
							
							});
						}
					}
				}
			}
		}
		
	
		{
			group2 = new Group(composite, SWT.NONE);
			FormLayout group2Layout = new FormLayout();
			group2.setLayout(group2Layout);
			FormData group2LData = new FormData();
			group2LData.width = 363;
			group2LData.height = 146;
			group2LData.left =  new FormAttachment(1, 1000, 0);
			group2LData.right =  new FormAttachment(1001, 1000, 0);
			group2LData.bottom =  new FormAttachment(1002, 1000, 0);
			group2LData.top =  new FormAttachment(0, 1000, 55);
			group2.setLayoutData(group2LData);
			group2.setText("Cost");
			{
				tableViewer1 = new TableViewer(group2, SWT.NONE);
				FormData tableViewer1LData = new FormData();
				tableViewer1LData.width = 247;
				tableViewer1LData.height = 89;
				tableViewer1LData.top =  new FormAttachment(0, 1000, 13);
				tableViewer1LData.right =  new FormAttachment(1000, 1000, -79);
				tableViewer1LData.bottom =  new FormAttachment(1000, 1000, -27);
				tableViewer1LData.left =  new FormAttachment(0, 1000, 20);
				tableViewer1.getControl().setLayoutData(tableViewer1LData);
				{
					dependencesCol = this.createTableViewerColumn("#deps", 60, 0, tableViewer1); 
					dependencesCol.setLabelProvider(new ColumnLabelProvider(){
						@Override
						public String getText(Object element) {
							Cost c = (Cost) element;
							return c.toString();
						}
					});
				}
				{
					highColumn = this.createTableViewerColumn("HIGH", 60, 1, tableViewer1); 
					highColumn.setLabelProvider(new CellLabelProvider() {
						
						@Override
						public void update(ViewerCell cell) {
							cell.setText(String.valueOf(((Cost)cell.getElement()).getHighCost()));
							
						}
					});
					highColumn.setEditingSupport(new HighCostEditingSupport(tableViewer1));

				}
				{
					mediumCol = this.createTableViewerColumn("MEDIUM", 60, 2, tableViewer1); 
					mediumCol.setLabelProvider(new CellLabelProvider() {
						
						@Override
						public void update(ViewerCell cell) {
							cell.setText(String.valueOf(((Cost)cell.getElement()).getMedCost()));
							
						}
					});
					mediumCol.setEditingSupport(new MediumCostEditingSupport(tableViewer1));
				}
				{
					lowColumn = this.createTableViewerColumn("LOW", 60, 3, tableViewer1); 
					lowColumn.setLabelProvider(new CellLabelProvider() {
						
						@Override
						public void update(ViewerCell cell) {
							cell.setText(String.valueOf(((Cost)cell.getElement()).getLowCost()));
							
						}
					});
					lowColumn.setEditingSupport(new LowCostEditingSupport(tableViewer1));
				}
				tableViewer1.setContentProvider(new ArrayContentProvider());
				tableViewer1.getTable().setHeaderVisible(true);
			}
								
		}

		int index = addPage(composite);
		setPageText(index, "Properties");
	}
	
	protected void loadGraph() throws IOException {
		String fileName = this.configuration.getFileName();
		if( fileName != null && !fileName.equals("")){
			//TODO cambiar extencion a leer
			//		String ext = this.configuration.getFileName().split(".")[1];
			//		GraphReader gr = GraphFactory.getInstance().createReader(ext);

			IGraphReader gr = GraphFactory.getInstance().createReader("EMF");
			gr.setSrc(fileName);
			GraphDirector gd = GraphDirector.getInstance();
			gd.setGraphReader(gr);
			graph = gd.createGraph();
			this.relationshipTable.setInput(graph.getRelationships());
			
		}
	}

	protected void refresTextEditor() {
		
		editor.getDocumentProvider().getDocument(editor.getEditorInput()).set(configuration.toXML());
		
	}

	private TableViewerColumn createTableViewerColumn(String title, int bound,final int colNumber, TableViewer viewer ) {
		TableViewerColumn viewerColumn = new TableViewerColumn(viewer,SWT.NONE);
		TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		return viewerColumn;
	}
	

	void createPage2() {

		Composite composite = new Composite(getContainer(), SWT.NONE);
		FillLayout layout = new FillLayout(org.eclipse.swt.SWT.HORIZONTAL);
		composite.setLayout(layout);
		composite.setSize(498, 100);
		{
			FormData relationshipTableLData = new FormData();
			relationshipTableLData.left =  new FormAttachment(0, 1000, 7);
			relationshipTableLData.top =  new FormAttachment(0, 1000, 12);
			relationshipTableLData.width = 217;
			relationshipTableLData.height = 64;
			relationshipTable = new TableViewer(composite, SWT.NONE);
			relationshipTable.getTable().setHeaderVisible(true);

			relSource = this.createTableViewerColumn("Source", 60, 1, relationshipTable);
			relSource.setLabelProvider(new ColumnLabelProvider(){
				@Override
				public String getText(Object element) {
					Relationship r = (Relationship) element;
					return r.getSrcModule().getName();
				}
			});
			relTarget = this.createTableViewerColumn("Target", 60, 2, relationshipTable);
			relTarget.setLabelProvider(new ColumnLabelProvider(){
				@Override
				public String getText(Object element) {
					Relationship r = (Relationship) element;
					return r.getTargetModule().getName();
				}
			});
			relCost = this.createTableViewerColumn("Prob", 60, 2, relationshipTable);
			relCost.setLabelProvider(new CellLabelProvider() {
				
				@Override
				public void update(ViewerCell cell) {
					cell.setText(String.valueOf(((Relationship)cell.getElement()).getCost()));
					
				}
			});
			relCost.setEditingSupport(new ProbRelationshipEditingSupport(relationshipTable));
			
			
			relationshipTable.setContentProvider(new ArrayContentProvider());
			relationshipTable.getTable().setBounds(0, 0, 81, 41);
		}

		int index = addPage(composite);
		setPageText(index, "Relationships");
	}
	
	/**
	 * Creates page 0 of the multi-page editor,
	 * which contains a text editor.
	 */
	void createPage0() {
		try {
			editor = new TextEditor();
			int index = addPage(editor, getEditorInput());
			setPageText(index, editor.getTitle());
			
		} catch (PartInitException e) {
			ErrorDialog.openError(
				getSite().getShell(),
				"Error creating nested text editor",
				null,
				e.getStatus());
		}
	}
	
//	/**
//	 * Creates page 2 of the multi-page editor,
//	 * which shows the sorted text.
//	 */
//	void createPage2() {
//		Composite composite = new Composite(getContainer(), SWT.NONE);
//		FillLayout layout = new FillLayout();
//		composite.setLayout(layout);
//		text = new StyledText(composite, SWT.H_SCROLL | SWT.V_SCROLL);
//		text.setEditable(false);
//
//		int index = addPage(composite);
//		setPageText(index, "Preview");
//	}
	/**
	 * Creates the pages of the multi-page editor.
	 */
	protected void createPages() {

		createPage0();
		this.loadFileToMen();
		createPage1();
		createPage2();
	}
	private void loadFileToMen() {
		String editorText = editor.getDocumentProvider().getDocument(editor.getEditorInput()).get();
		configuration = TransformConfiguration.loadFromXML(editorText);
		
	}

	/**
	 * The <code>MultiPageEditorPart</code> implementation of this 
	 * <code>IWorkbenchPart</code> method disposes all nested editors.
	 * Subclasses may extend.
	 */
	public void dispose() {
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
		super.dispose();
	}
	/**
	 * Saves the multi-page editor's document.
	 */
	public void doSave(IProgressMonitor monitor) {
		getEditor(0).doSave(monitor);
	}
	/**
	 * Saves the multi-page editor's document as another file.
	 * Also updates the text for page 0's tab, and updates this multi-page editor's input
	 * to correspond to the nested editor's.
	 */
	public void doSaveAs() {
		IEditorPart editor = getEditor(0);
		editor.doSaveAs();
		setPageText(0, editor.getTitle());
		setInput(editor.getEditorInput());
	}
	/* (non-Javadoc)
	 * Method declared on IEditorPart
	 */
	public void gotoMarker(IMarker marker) {
		setActivePage(0);
		IDE.gotoMarker(getEditor(0), marker);
	}
	/**
	 * The <code>MultiPageEditorExample</code> implementation of this method
	 * checks that the input is an instance of <code>IFileEditorInput</code>.
	 */
	public void init(IEditorSite site, IEditorInput editorInput)
		throws PartInitException {
		if (!(editorInput instanceof IFileEditorInput))
			throw new PartInitException("Invalid Input: Must be IFileEditorInput");
		super.init(site, editorInput);
	}
	/* (non-Javadoc)
	 * Method declared on IEditorPart.
	 */
	public boolean isSaveAsAllowed() {
		return true;
	}
	/**
	 * Calculates the contents of page 2 when the it is activated.
	 */
	protected void pageChange(int newPageIndex) {
		super.pageChange(newPageIndex);
		if (newPageIndex == 0) {
			refresTextEditor();	
		}
		else{
			this.loadFileToMen();
			if(newPageIndex == 1){
				updateCosts();
			}
			if (newPageIndex == 2){
				
			}
		}
		
	}
	private void updateCosts() {
		tableViewer1.setInput(this.configuration.getCosts());		
	}

	/**
	 * Closes all project files on project close.
	 */
	public void resourceChanged(final IResourceChangeEvent event){
		if(event.getType() == IResourceChangeEvent.PRE_CLOSE){
			Display.getDefault().asyncExec(new Runnable(){
				public void run(){
					IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
					for (int i = 0; i<pages.length; i++){
						if(((FileEditorInput)editor.getEditorInput()).getFile().getProject().equals(event.getResource())){
							IEditorPart editorPart = pages[i].findEditor(editor.getEditorInput());
							pages[i].closeEditor(editorPart,true);
						}
					}
				}            
			});
		}
	}
	
	/**
	 * Sets the font related data to be applied to the text in page 2.
	 */
	void setFont() {
		FontDialog fontDialog = new FontDialog(getSite().getShell());
		fontDialog.setFontList(text.getFont().getFontData());
		FontData fontData = fontDialog.open();
		if (fontData != null) {
			if (font != null)
				font.dispose();
			font = new Font(text.getDisplay(), fontData);
			text.setFont(font);
		}
	}
//	/**
//	 * Sorts the words in page 0, and shows them in page 2.
//	 */
//	void sortWords() {
//
//		String editorText =
//			editor.getDocumentProvider().getDocument(editor.getEditorInput()).get();
//
//		StringTokenizer tokenizer =
//			new StringTokenizer(editorText, " \t\n\r\f!@#\u0024%^&*()-_=+`~[]{};:'\",.<>/?|\\");
//		ArrayList editorWords = new ArrayList();
//		while (tokenizer.hasMoreTokens()) {
//			editorWords.add(tokenizer.nextToken());
//		}
//
//		Collections.sort(editorWords, Collator.getInstance());
//		StringWriter displayText = new StringWriter();
//		for (int i = 0; i < editorWords.size(); i++) {
//			displayText.write(((String) editorWords.get(i)));
//			displayText.write(System.getProperty("line.separator"));
//		}
//		text.setText(displayText.toString());
//	}
}
